# -*- coding: utf-8 -*-
from __future__ import absolute_import

import re

from PyQt4.QtCore import QObject
from PyQt4.QtCore import QProcess
from PyQt4.QtCore import Qt
from PyQt4.QtCore import SIGNAL
from PyQt4.QtGui import QInputDialog
from PyQt4.QtGui import QMessageBox
from PyQt4.QtGui import QShortcut
from PyQt4.QtGui import QKeySequence
from PyQt4.QtGui import QMessageBox

from ninja_ide.core import file_manager
import webbrowser
from ninja_ide.tools import ui_tools
from ninja_ide.tools import locator
from ninja_ide.gui.editor import helpers
from ninja_ide.gui.dialogs import from_import_dialog
from ninja_ide.tools import runner


__actionsInstance = None


def Actions(*args, **kw):
    global __actionsInstance
    if __actionsInstance is None:
        __actionsInstance = __Actions(*args, **kw)
    return __actionsInstance


class __Actions(QObject):

    def __init__(self):
        QObject.__init__(self)
        #Definition Locator
        self._locator = locator.Locator()

    def install_shortcuts(self, ide):
        self._ide = ide
        shortCloseTab = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W), self._ide)
        shortNew = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N), self._ide)
        shortNewProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_M),
            self._ide)
        shortOpen = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_O), self._ide)
        shortOpenProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P),
            self._ide)
        shortSave = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_S), self._ide)
        shortSaveProject = QShortcut(
            QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S), self._ide)
        shortPrint = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_I), self._ide)
        shortRedo = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Y), self._ide)
        shortComment = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_D), self._ide)
        shortHorizontalLine = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_R),
            self._ide)
        shortTitleComment = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_T),
            self._ide)
        shortIndentLess = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Tab),
            self._ide)
        shortHideMisc = QShortcut(QKeySequence(Qt.Key_F4), self._ide)
        shortHideEditor = QShortcut(QKeySequence(Qt.Key_F3), self._ide)
        shortHideExplorer = QShortcut(QKeySequence(Qt.Key_F2), self._ide)
        shortRunFile = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F6), self._ide)
        shortRunProject = QShortcut(QKeySequence(Qt.Key_F6), self._ide)
        shortStopExecution = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F5),
            self._ide)
        shortHideAll = QShortcut(QKeySequence(Qt.Key_F11), self._ide)
        shortFullscreen = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F11),
            self._ide)
        shortFind = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self._ide)
        shortFindReplace = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_H),
            self._ide)
        shortFindWithWord = QShortcut(QKeySequence(Qt.CTRL + \
            Qt.Key_1), self._ide)
        shortHelp = QShortcut(QKeySequence(Qt.Key_F1), self._ide)
        shortSplitHorizontal = QShortcut(QKeySequence(Qt.Key_F10), self._ide)
        shortSplitVertical = QShortcut(QKeySequence(Qt.Key_F9), self._ide)
        shortFollowMode = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F10),
            self._ide)
        shortReloadFile = QShortcut(QKeySequence(Qt.Key_F5), self._ide)
        shortShowProjectsTree = QShortcut(QKeySequence(Qt.ALT + Qt.Key_1),
            self._ide)
        shortShowSymbolsTree = QShortcut(QKeySequence(Qt.ALT + Qt.Key_2),
            self._ide)
        shortShowWebInspector = QShortcut(QKeySequence(Qt.ALT + Qt.Key_3),
            self._ide)
        shortJump = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J), self._ide)
        shortFindInFiles = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_L),
            self._ide)
        shortImport = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_U), self._ide)
        shortGoToDefinition= QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Return),
            self._ide)
        shortCodeLocator = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_K),
            self._ide)

        #Connect Shortcuts Signals
        self.connect(shortCodeLocator, SIGNAL("activated()"),
            self._ide._status.show_locator)
        self.connect(shortGoToDefinition, SIGNAL("activated()"),
            self._editor_go_to_definition)
        self.connect(shortRedo, SIGNAL("activated()"),
            self._editor_redo)
        self.connect(shortHorizontalLine, SIGNAL("activated()"),
            self._editor_insert_horizontal_line)
        self.connect(shortTitleComment, SIGNAL("activated()"),
            self._editor_insert_title_comment)
        self.connect(shortFollowMode, SIGNAL("activated()"),
            self._ide._mainContainer.show_follow_mode)
        self.connect(shortReloadFile, SIGNAL("activated()"),
            self._ide._mainContainer.reload_file)
        self.connect(shortSplitHorizontal, SIGNAL("activated()"),
            lambda: self._ide._mainContainer.split_tab(True))
        self.connect(shortSplitVertical, SIGNAL("activated()"),
            lambda: self._ide._mainContainer.split_tab(False))
        self.connect(shortNew, SIGNAL("activated()"),
            self._ide._mainContainer.add_editor)
        self.connect(shortNewProject, SIGNAL("activated()"),
            self._ide._explorer.create_new_project)
        self.connect(shortHideMisc, SIGNAL("activated()"),
            self._ide._central.change_misc_visibility)
        self.connect(shortHideEditor, SIGNAL("activated()"),
            self._ide._central.change_main_visibility)
        self.connect(shortHideExplorer, SIGNAL("activated()"),
            self._ide._central.change_explorer_visibility)
        self.connect(shortHideAll, SIGNAL("activated()"),
            self._hide_all)
        self.connect(shortJump, SIGNAL("activated()"),
            self._ide._mainContainer.editor_jump_to_line)
        self.connect(shortFullscreen, SIGNAL("activated()"),
            self._fullscreen_mode)
        self.connect(shortShowSymbolsTree, SIGNAL("activated()"),
            self._ide._explorer.show_symbols_tree)
        self.connect(shortShowProjectsTree, SIGNAL("activated()"),
            self._ide._explorer.show_project_tree)
        self.connect(shortShowWebInspector, SIGNAL("activated()"),
            self._ide._explorer.show_web_inspector)
        self.connect(shortOpen, SIGNAL("activated()"),
            self._ide._mainContainer.open_file)
        self.connect(shortOpenProject, SIGNAL("activated()"),
            self._ide._explorer.open_project_folder)
        self.connect(shortCloseTab, SIGNAL("activated()"),
            self._ide._mainContainer._actualTab.close_tab)
        self.connect(shortSave, SIGNAL("activated()"),
            self._ide._mainContainer.save_file)
        self.connect(shortSaveProject, SIGNAL("activated()"),
            self.save_project)
        self.connect(shortPrint, SIGNAL("activated()"),
            self.print_file)
        self.connect(shortFind, SIGNAL("activated()"),
            self._ide._status.show)
        self.connect(shortFindWithWord, SIGNAL("activated()"),
            self._ide._status.show_with_word)
        self.connect(shortFindReplace, SIGNAL("activated()"),
            self._ide._status.show_replace)
        self.connect(shortRunFile, SIGNAL("activated()"),
            self._execute_file)
        self.connect(shortRunProject, SIGNAL("activated()"),
            self._execute_project)
        self.connect(shortStopExecution, SIGNAL("activated()"),
            self._kill_execution)
        self.connect(shortIndentLess, SIGNAL("activated()"),
            self._editor_indent_less)
        self.connect(shortComment, SIGNAL("activated()"),
            self._editor_comment)
        self.connect(shortHelp, SIGNAL("activated()"),
            self._ide._mainContainer.show_python_doc)
        self.connect(shortImport, SIGNAL("activated()"),
            self.import_from_everywhere)
        self.connect(shortFindInFiles, SIGNAL("activated()"),
            self._ide._misc.show_find_in_files_widget)

        #Connect SIGNALs from other objects
        self.connect(self._ide._mainContainer._tabMain,
            SIGNAL("runFile()"), self._execute_file)
        self.connect(self._ide._mainContainer._tabSecondary,
            SIGNAL("runFile()"), self._execute_file)
        self.connect(self._ide._mainContainer._tabMain,
            SIGNAL("addToProject(QString)"), self._add_file_to_project)
        self.connect(self._ide._mainContainer._tabSecondary,
            SIGNAL("addToProject(QString)"), self._add_file_to_project)
        self.connect(self._ide._mainContainer,
            SIGNAL("openProject(QString)"), self.open_project)

    def _add_file_to_project(self, path):
        pathProject = self._ide._explorer.get_actual_project()
        addToProject = ui_tools.AddToProject(pathProject, self._ide)
        addToProject.exec_()
        if not addToProject.pathSelected:
            return
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if not editorWidget.ID:
            name = unicode(QInputDialog.getText(None, self.tr("Add File To Project"),
                self.tr("File Name:"))[0])
            if not name:
                QMessageBox.information(self, self.tr("Indalid Name"),
                    self.tr("The file name is empty, please enter a name"))
                return
        else:
            name = file_manager.get_basename(editorWidget.ID)
        path = file_manager.create_abs_path(
            unicode(addToProject.pathSelected), name)
        if not file_manager.file_exists(path):
            path = file_manager.store_file_content(
                path, editorWidget.get_text())
            editorWidget.ID = path
            self._ide._explorer.add_existing_file(path)
            self._ide.change_window_title(path)
            name = file_manager.get_basename(path)
            self._ide._mainContainer._actualTab.setTabText(
                self._ide._mainContainer._actualTab.currentIndex(), name)
            editorWidget._file_saved()
        else:
            QMessageBox.information(self, self.tr("File Already Exists"),
                    self.tr("Invalid Path: the file already exists."))

    def import_from_everywhere(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            text = unicode(editorWidget.get_text())
            froms = re.findall('^from (.*)', text, re.MULTILINE)
            fromSection = list(set([f.split(' import')[0] for f in froms]))
            dialog = from_import_dialog.FromImportDialog(fromSection,
                editorWidget, self._ide)
            dialog.show()

    def open_project(self, path):
        self._ide._explorer.open_project_folder(unicode(path))

    def count_file_code_lines(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))',
                str(editorWidget.get_text()),re.M)
            resume = self.tr("Lines code: ") + unicode(
                editorWidget.blockCount() - len(blanks)) + "\n"
            resume += self.tr("Blanks and commented lines: ") + \
                unicode(len(blanks)) + "\n\n"
            resume += self.tr("Total lines: ") + \
                unicode(editorWidget.blockCount())
            msgBox = QMessageBox( QMessageBox.Information,
                self.tr("Summary of lines"), resume,
                QMessageBox.Ok, editorWidget)
            msgBox.exec_()

    def _execute_file(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            if not editorWidget.ID:
                self._ide._mainContainer.save_file()
            ext = file_manager.get_file_extension(editorWidget.ID)
            if ext == '.py':
                self._ide._misc.run_application(editorWidget.ID)
            elif ext == '.html':
                self._ide._misc.render_web_page(editorWidget.ID)

    def _execute_project(self):
        mainFile = self._ide._explorer.get_project_main_file()
        if not mainFile and self._ide._explorer._treeProjects and \
        self._ide._explorer._treeProjects._actualProject:
            self._ide._explorer._treeProjects.open_project_properties()
        elif mainFile:
            self.save_project()
            path = self._ide._explorer.get_actual_project()
            mainFile = file_manager.create_abs_path(path, mainFile)
            self._ide._misc.run_application(mainFile)

    def _kill_execution(self):
        self._ide._misc.kill_application()

    def _fullscreen_mode(self):
        if self._ide.isFullScreen():
            self._ide.showMaximized()
        else:
            self._ide.showFullScreen()

    def _editor_redo(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            editorWidget.redo()

    def _editor_indent_less(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            editorWidget.indent_less()

    def _editor_indent_more(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            editorWidget.indent_more()

    def _editor_comment(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.comment(editorWidget)

    def _editor_insert_horizontal_line(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.insert_horizontal_line(editorWidget)

    def _editor_insert_title_comment(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.insert_title_comment(editorWidget)

    def _editor_remove_trailing_spaces(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.remove_trailing_spaces(editorWidget)

    def _editor_replace_tabs_with_spaces(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.replace_tabs_with_spaces(editorWidget)

    def _editor_move_up(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.move_up(editorWidget)

    def _editor_move_down(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.move_down(editorWidget)

    def _editor_duplicate(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            helpers.duplicate(editorWidget)

    def _editor_go_to_definition(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            editorWidget.go_to_definition()

    def reset_editor_flags(self):
        self._ide._mainContainer.reset_editor_flags()

    def preview_in_browser(self):
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget:
            if not editorWidget.ID:
                self._ide._mainContainer.save_file()
            ext = file_manager.get_file_extension(editorWidget.ID)
            if ext == '.html':
                webbrowser.open(editorWidget.ID)

    def _hide_all(self):
        if self._ide.menuBar().isVisible():
            self._ide._explorer.hide()
            self._ide._misc.hide()
            self._ide._toolbar.hide()
            self._ide.menuBar().hide()
        else:
            self._ide._explorer.show()
            self._ide._toolbar.show()
            self._ide.menuBar().show()

    def save_project(self):
        path = self._ide._explorer.get_actual_project()
        if path:
            self._ide._mainContainer.save_project(path)

    def print_file(self):
        """Call the print of ui_tool

        Call print of ui_tool depending on the focus of the application"""
        #TODO: Add funtionality for proyect tab and methods tab
        editorWidget = self._ide._mainContainer.get_actual_editor()
        if editorWidget is not None:
            fileName = "newDocument.pdf"
            if editorWidget.ID:
                fileName = file_manager.get_basename(
                    editorWidget.ID)
                fileName = fileName[:fileName.rfind('.')] + '.pdf'
            ui_tools.print_file(fileName, editorWidget.print_)

    def locate_function(self, function, filePath, isVariable):
        self._locator.navigate_to(unicode(function),
            unicode(filePath), isVariable)
